/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bizfty.apiexecutor.gateways;

import com.bizfty.api.apiexecutor.beans.DeployRequest;
import com.bizfty.api.apiexecutor.beans.DeployResponse;
import com.bizfty.api.commons.beans.faults.BusinessException;
import com.bizfty.api.commons.beans.faults.TechnicalException;
import com.bizfty.api.apiexecutor.gateways.ApiExe;
import com.bizfty.api.commons.beans.MediaType;
import com.bizfty.apiexecutor.Application;
import com.bizfty.apiexecutor.classloader.ApplicationContextUtil;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.servlet.ServletRegistration;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.apache.commons.io.FileUtils;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

/**
 *
 * @author johns
 */
@WebService(targetNamespace = "http://gateways.apiexecutor.api.bizfty.com", name = "ApiExe", portName = "ApiExePort")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
@Component("apiExe")
@Path("/")
public class ApiExeImpl implements ApiExe {

    private static Logger logger = LoggerFactory.getLogger(ApiExeImpl.class);

    @Value("${deploy.path}")
    private String deployPath;

    @Autowired
    private WebApplicationContext applicationContext;

    @Override
    @POST
    @Path("/deploy")
    @Consumes(MediaType.APPLICATION_JSON_VALUE)
    @Produces(MediaType.APPLICATION_JSON_UTF8_VALUE)
    public DeployResponse deploy(DeployRequest request) throws BusinessException, TechnicalException {
        File file = new File(deployPath + buildJarName(request.getModule(), request.getVersion()));
        try {
            byte[] in = Base64.decodeBase64(request.getFileContext());
            FileUtils.writeByteArrayToFile(file, in);
            URL url = new URL("jar:" + file.toURI().toURL().toString() + "!/");

            Application.executorClassLoader.loadJarFile(url, request.getModule());
            // 获取bean工厂并转换为DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
            
            
//            AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
//            context.setParent(contextUtil.getApplicationContext());
//            context.setConfigLocation(url.toString() + "integration.xml");
            XmlWebApplicationContext context = new XmlWebApplicationContext();
            context.setParent(applicationContext);
            //context.setConfigLocation(url.toString() + "integration.xml");
            context.setConfigLocation("classpath*:integration.xml");
            context.refresh();
            DispatcherServlet dispatcherServlet = new DispatcherServlet(context);

            ServletRegistration.Dynamic servlet = applicationContext.getServletContext().addServlet(buildPath(request.getModule(), request.getVersion()), dispatcherServlet);
            servlet.addMapping(buildPath(request.getModule(), request.getVersion()) + "/*");
            servlet.setLoadOnStartup(1);
            servlet.setAsyncSupported(false);

            //通过BeanDefinitionBuilder创建bean定义
//            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ServletRegistrationBean.class);
//            beanDefinitionBuilder.addConstructorArgValue(dispatcherServlet);
//            beanDefinitionBuilder.addConstructorArgValue(buildPath(request.getModule(), request.getVersion()) + "/*");
//            beanDefinitionBuilder.addPropertyValue("name", buildPath(request.getModule(), request.getVersion()));
//            beanFactory.registerBeanDefinition(buildPath(request.getModule(), request.getVersion()), beanDefinitionBuilder.getRawBeanDefinition());
//            ServletRegistrationBean registration = (ServletRegistrationBean) beanFactory.getBean(buildPath(request.getModule(), request.getVersion()));
//            logger.debug(registration.getServletName());
//            logger.debug(registration.getUrlMappings().toString());
        } catch (IOException ex) {
            logger.error("获取上传文件发生IO错误！", ex);
        }
        return new DeployResponse();
    }

    private String buildJarName(String module, String version) {
        return module + "-" + version + ".jar";
    }

    private String buildPath(String module, String version) {
        return module + "/" + version;
    }

}
